package arithmetic2;

import arithmetic.A_09_BinaryTree;

import java.util.HashMap;

/**
 * @author macpro
 * @date 2019-08-03
 * @function
 *
 * 给定一个非空二叉树，返回其最大路径和。
 *
 * 本题中，路径被定义为一条从树中任意节点出发，达到任意节点的序列。该路径至少包含一个节点，且不一定经过根节点。
 *
 * 示例 1:
 *
 * 输入: [1,2,3]
 *
 *        1
 *       / \
 *      2   3
 *
 * 输出: 6
 * 示例 2:
 *
 * 输入: [-10,9,20,null,null,15,7]
 *
 *    -10
 *    / \
 *   9  20
 *     /  \
 *    15   7
 *
 * 输出: 42
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/binary-tree-maximum-path-sum
 */
public class T_124_BinaryTreeMaxPathSum {

    public static void main(String[] args) {
        int i = maxPathSum(A_09_BinaryTree.getTreeRootNode());
        System.out.println(i);
    }

    // 1 understanding topic
    // 2 possible solution
    // 3 coding
    // 4 test sample
    public static int maxPathSum(TreeNode root) {
        // TODO: 2019-08-03
        // 1输入的数组转换成 tree
        // 2 每个节点最大值，从下往上,
        // 3 动态规划，局部最优解，递推，
        // 4 定义状态
        //      0当前回路最大值，root + left +right , dp
        //      1当前非回路最大值 root ,root+ left,root +right,
        //      2当前不包含此节点最大值  MAX (left right ) 那个节点的最大值
        //      dp[当前非回路最大值][回路最大值]
        //      dp[0-i][0 1] 如何存储判断，map node -- int []遍历方式，底--》上   左右根
        if (root == null) {
            return 0;
        }
        HashMap<TreeNode, int[]> treeNodeHashMap = new HashMap<>();
//        int[] res = {0};//todo 错误，应该为第一个value
        int[] res = {root.val};//todo 错误，应该为第一个value

        searchNode(root,treeNodeHashMap,res);
        return res[0];
    }

    private static void searchNode(TreeNode root, HashMap<TreeNode, int[]> treeNodeHashMap, int[] res) {
        if (root == null) {
            return;
        }
        searchNode(root.left, treeNodeHashMap, res);
        searchNode(root.right, treeNodeHashMap, res);
        System.out.println(root.val);
        int rV = res[0];
        int[] valus = new int[2];
        int left =0;
        if (root.left!=null){
           left=treeNodeHashMap.get(root.left)[1];
        }
        int right=0;
        if (root.right!=null){
            right = treeNodeHashMap.get(root.right)[1];
        }
        valus[1]=Math.max(root.val,Math.max(root.val+left,root.val+right));
        valus[0]=Math.max(valus[1],root.val+left+right);//currentMaxValue
        treeNodeHashMap.put(root,valus);
        if (valus[0]>rV){
            res[0]=valus[0];
        }
    }

    /**
     * todo 官方题解
     * 作者：LeetCode
     *     链接：https://leetcode-cn.com/problems/two-sum/solution/er-cha-shu-de-zui-da-lu-jing-he-by-leetcode/
     *     来源：力扣（LeetCode）
     *     著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。
     */

    int max_sum = Integer.MIN_VALUE;

    /**
     * 参数是一个顶点，计算它及其子树的最大贡献。
     * @param node
     * @return
     */
    public int max_gain(TreeNode node) {
        if (node == null) return 0;

        // max sum on the left and right sub-trees of node
        int left_gain = Math.max(max_gain(node.left), 0);
        int right_gain = Math.max(max_gain(node.right), 0);

        // the price to start a new path where `node` is a highest node
        int price_newpath = node.val + left_gain + right_gain;

        // update max_sum if it's better to start a new path
        max_sum = Math.max(max_sum, price_newpath);

        // for recursion :
        // return the max gain if continue the same path
        return node.val + Math.max(left_gain, right_gain);
    }

    public int maxPathSumOfficial(TreeNode root) {
        max_gain(root);
        return max_sum;
    }



}
